#pragma once
#include "CPanel.h"
#include "SpanStoreEntry.h"

class CDefinitionBase;
class CRowDefinitionCollection;
class CColumnDefinitionCollection;

class CGrid :
	public CPanel
{

private: 
	HRESULT ValidateDefinitionStructure();
	HRESULT ValidateDefinitionsLayout(CCollection * pDefinitions, XUINT8 fTreatStarAsAuto);
	HRESULT ValidateCells(XUINT32 cChildren, CUIElement * * pChildren);
	XUINT32 GetRowIndex(CUIElement * pChild);
	XUINT32 GetColumnIndex(CUIElement * pChild);
	CDefinitionBase * GetRow(CUIElement * pChild);
	CDefinitionBase * GetColumn(CUIElement * pChild);
	XUINT32 GetRowSpan(CUIElement * pChild);
	XUINT32 GetColumnSpan(CUIElement * pChild);
	HRESULT MeasureCellsGroup(XUINT32 cellsHead, XUINT32 cellCount, struct XSIZEF referenceSize, XUINT8 ignoreColumnDesiredSize, XUINT8 forceRowToInfinity);
	HRESULT MeasureCell(XUINT32 cell, XUINT8 forceRowToInfinity);
	XUINT8 GetLengthTypeForRange(CCollection * definitions, XUINT32 start, XUINT32 count);
	XFLOAT GetMeasureSizeForRange(CCollection * definitions, XUINT32 start, XUINT32 count);
	XFLOAT GetFinalSizeForRange(CCollection * definitions, XUINT32 start, XUINT32 count);
	XFLOAT CalculateDesiredSize(CCollection * definitions);
	void SortDefinitionsForOverflowSizeDistribution(CDefinitionBase * * ppDefinitions, XUINT32 cDefinitions);
	void SortDefinitionsForStarSizeDistribution(CDefinitionBase * * ppDefinitions, XUINT32 cDefinitions);
	void SortDefinitionsForSpanPreferredDistribution(CDefinitionBase * * ppDefinitions, XUINT32 cDefinitions);
	void SortDefinitionsForSpanMaxSizeDistribution(CDefinitionBase * * ppDefinitions, XUINT32 cDefinitions);
	HRESULT SetFinalSize(CCollection * definitions, XFLOAT finalSize);
	HRESULT ResolveStar(CCollection * definitions, XFLOAT availableSize);
	HRESULT EnsureTempDefinitionsStorage(XUINT32 minCount);
	void SetGridFlag(XUINT8 mask);
	XUINT8 GetGridFlag(XUINT8 mask);
	void DistributeStarSpace(CDefinitionBase * * ppStarDefinitions, XUINT32 cStarDefinitions, XFLOAT availableSize, XFLOAT * pTotalResolvedSize, XUINT8 releaseDefinitions);
	HRESULT RegisterSpan(CXcpList<SpanStoreEntry> * * ppSpanStore, XUINT32 spanStart, XUINT32 spanCount, XUINT8 isColumnDefinition, XFLOAT elementSize);
	HRESULT EnsureMinSizeInDefinitionRange(CCollection * pDefinitions, XUINT32 spanStart, XUINT32 spanCount, XFLOAT childDesiredSize);
	void LockDefinitions();
	void UnlockDefinitions();

protected: 
	CGrid(CCoreServices * pCore); 
	virtual HRESULT MeasureOverride(struct XSIZEF availableSize, struct XSIZEF & desiredSize);
	virtual HRESULT ArrangeOverride(struct XSIZEF finalSize, struct XSIZEF & newFinalSize);
public: 
	virtual ~CGrid();
	static HRESULT Create(CDependencyObject * * ppObject, CREATEPARAMETERS * pCreate);
	virtual XUINT32 GetTypeIndex() const;
	CRowDefinitionCollection * m_pRowDefinitions;
	CColumnDefinitionCollection * m_pColumnDefinitions;
private: 
	CRowDefinitionCollection * m_pRows;
	CColumnDefinitionCollection * m_pColumns;
	struct CellCache * m_pCells;
	CDefinitionBase * * m_ppTempDefinitions;
	XUINT32 m_cTempDefinitions;
	XUINT32 m_cellGroup1;
	XUINT32 m_cellGroup2;
	XUINT32 m_cellGroup3;
	XUINT32 m_cellGroup4;
	struct 
	{
		XUINT8 m_fGridFlags:3;
	};
	
};
